El primero está basado en un histórico de ventas de videojuegos de varias compañÃas en distintas plataformas desde el inicio del mercado de este producto. Se pretende obtener tendencias, deducir quién controla el mercado, puntos de crisis o cambio de consumo, y cuáles son las plataformas que dominan el mercado actual.
Ideas a estudiar en el dataset -Comparar las ventas entre regiones. Observar relaciones y modelos de influencia entre las mismas. -Ver qué géneros son más populares en regiones y han cambiado a lo largo del tiempo significativamente. -El alzamiento y caÃda de diferentes plataformas a lo largo de los años.
library(reshape2) #facilita la trasnformación entre diferentes formatos de datos.
library(plotly) #https://plot.ly/r/
Loading required package: ggplot2
Use suppressPackageStartupMessages() to eliminate package startup messages.
Attaching package: ‘plotly’
The following object is masked from ‘package:ggplot2’:
last_plot
The following object is masked from ‘package:stats’:
filter
The following object is masked from ‘package:graphics’:
layout
video_games<-read.csv("recursos/vgsales.csv")
typeof(video_games)
[1] "list"
head(video_games)
video_games$Year <- ordered(video_games$Year)
video_games <- video_games[video_games$Year<2017,]
video_games
Vamos a ver la proporción de ventas en relación al total
num_Sales <- video_games[,c("NA_Sales","EU_Sales","JP_Sales","Other_Sales","Global_Sales")]
apply(num_Sales,2,sum)/apply(num_Sales['Global_Sales'],2,sum)*100
NA_Sales EU_Sales JP_Sales Other_Sales Global_Sales
49.128687 27.314224 14.560625 8.945445 100.000000
De forma general puede apreciarse que hay una subida prograsiva desde 1996 hasta 2008. A partir de este momento comienza la caidahasta 2016.
ggplot(data=video_games, aes(x=Year, y=Global_Sales, fill=Genre)) +
geom_bar(stat="identity")

ggplotly()
-Comparar las ventas entre regiones. Observar relaciones y modelos de influencia entre las mismas.
head(video_games)
#video_games_NA=video_games[c("Year","NA_Sales")]
#video_games_EU=video_games[c("Year","EU_Sales")]
#video_games_JP=video_games[c("Year","JP_Sales")]
ggplot(data=video_games, aes(x=Year, y=NA_Sales, fill=Genre)) +
geom_bar(stat="identity")

ggplot(data=video_games, aes(x=Year, y=EU_Sales, fill=Genre)) +
geom_bar(stat="identity")

ggplot(data=video_games, aes(x=Year, y=JP_Sales, fill=Genre)) +
geom_bar(stat="identity")

ggplot(data=video_games, aes(x=Year, y=Other_Sales, fill=Genre)) +
geom_bar(stat="identity")

Se aprecia que hay una influencia clara entre Europa y EEUU. Japón va un poco mas por libre, aunque se puede observar que los grandes cambios de tendencia también le afectan. Se podrÃa decir también que Japón es quien inicia esas tendencias. Cuando empiezan a subir las ventas, a los pocos años suben también en EEUU y Europa. Lo mismo cuando comienzan a caer las ventas. El resto del mundo sigue también la tendencia de Europa y EEUU.
#Preparo los datos para poder mostrar una tendencia de ventas por región
library(dplyr) #funciones para manipular data frames.
Attaching package: ‘dplyr’
The following objects are masked from ‘package:stats’:
filter, lag
The following objects are masked from ‘package:base’:
intersect, setdiff, setequal, union
na <- video_games %>% select(Year,NA_Sales) %>% group_by(Year) %>% summarise(s=sum(NA_Sales))
eu <- video_games %>% select(Year,EU_Sales) %>% group_by(Year) %>% summarise(s=sum(EU_Sales))
jp <- video_games %>% select(Year,JP_Sales) %>%group_by(Year) %>% summarise(s=sum(JP_Sales))
oth <- video_games %>% select(Year,Other_Sales) %>% group_by(Year) %>% summarise(s=sum(Other_Sales))
data_sales <- data.frame(year = c(1980:2016),oth$s,jp$s,eu$s,na$s)
data_sales
ggplot(data_sales, aes((year))) +
geom_line(aes(y = na$s , colour = "NA_Sales"),size=1) +
geom_line(aes(y = eu$s, colour = "EU_Sales"),size=1)+
geom_line(aes(y= jp$s ,colour='JP_Sales'),size=1)+
geom_line(aes(y=oth$s,colour='Other_Sales'),size=1) + ylab('Ventas en Millones') +
scale_x_continuous(breaks = scales::pretty_breaks(n = 9)) + #Numero de divisiones en X.
ggtitle("Evolución de ventas a lo largo del tiempo") +
#theme(axis.text.x = element_text(angle = 90, size = 10, vjust = 0.4),legend.position = "top")
theme(plot.background = element_rect(fill = "grey"),legend.text = element_text(size = 8, colour = "blue"),legend.title = element_text(face="bold"),legend.position = "top")

#hay diferentes tipos de themes predefinidos: theme_bf... theme_gray... Ver https://ggplot2.tidyverse.org/reference/theme.html
Se observa una dominación en las ventas por parte de NA entre 2000 y 2010, A partir de 2008 y coincidiendo con la crisis global económica, hay una caÃda fuerte en todas las regiones y la dominación cesa.
Hay por lo tanto puntos crÃticos en la evolución de las ventas en 1995, 2000 y 2008 (se podrÃa indagar qué motivos forzaron los cambios en las fechas previas no comentadas).
A su vez se observa que la serie NA y EU están fuertemente ligadas.
-El alzamiento y caÃda de diferentes plataformas a lo largo de los años.
platforms <- video_games[,c("Platform","Year","Global_Sales")]
platforms <- platforms %>% group_by(Platform,Year) %>% summarise_all(funs(sum))
platforms_1980<-subset(platforms,Year<1990,select = Platform:Global_Sales)
platforms_1990<-subset(platforms,Year>=1990 & Year<2000,select = Platform:Global_Sales)
platforms_2000<-subset(platforms,Year>=2000 & Year<2010,select = Platform:Global_Sales)
platforms_2010<-subset(platforms,Year>=2010,select = Platform:Global_Sales)
sp <- ggplot(platforms_1980, aes(x=Year, y=Global_Sales)) +
geom_point(shape=1) +
geom_line(group = 1)
sp + facet_grid(Platform ~ .)

sp <- ggplot(platforms_1990, aes(x=Year, y=Global_Sales)) +
geom_point(shape=1) +
geom_line(group = 1)
sp + facet_wrap(Platform ~ ., ncol=3)

sp <- ggplot(platforms_2000, aes(x=Year, y=Global_Sales)) +
geom_point(shape=1) +
geom_line(group = 1)
sp + facet_wrap(Platform ~ ., ncol=3)

sp <- ggplot(platforms_2010, aes(x=Year, y=Global_Sales)) +
geom_point(shape=1) +
geom_line(group = 1)
sp + facet_wrap(Platform ~ ., ncol=3)

#Para los gráficos de lÃneas, los puntos de datos deben agruparse para que sepa qué puntos conectar. En este caso, es simple: todos los puntos deben estar conectados, por lo que group = 1. Cuando se utilizan más variables y se dibujan varias lÃneas, la agrupación de lÃneas se realiza generalmente por variable.
Ver qué géneros son más populares en regiones y han cambiado a lo largo del tiempo significativamente.
Vamos a ver el TOP de los géneros por año
#La función top_n te permite quedarte con el primer valor:
top_genre_year <- video_games[,c("Genre","Year","Global_Sales")]
top_genre_year <- top_genre_year %>% group_by(Year,Genre) %>% summarise(ventas=sum(Global_Sales)) %>% top_n(1)
Selecting by ventas
top_genre_japan <- video_games[,c("Genre","Year","JP_Sales")]
top_genre_japan <- top_genre_japan %>% group_by(Year,Genre) %>% summarise(ventas=sum(JP_Sales)) %>% top_n(1)
Selecting by ventas
ggplot(data=top_genre_year, aes(x=Year, y=ventas, fill=Genre)) +
geom_bar(stat="identity") +
ggtitle("Top Genero por año") +
theme(axis.text.x = element_text(angle = 90, size = 10, vjust = 0.4),legend.position = "top")

ggplot(data=top_genre_japan, aes(x=Year, y=ventas, fill=Genre)) +
geom_bar(stat="identity") +
ggtitle("Top Genero por año Japon") +
theme(axis.text.x = element_text(angle = 90, size = 10, vjust = 0.4),legend.position = "top")

Observamos que la preferencia en género de videojuego en Japón es por los juegos de rol mientras que globalmente es por los de acción. Esto es una caracterÃstica cualitativa diferenciadora de este mercado respecto al global.
Realizamos un contraste Chi Cuadrado de bondad de ajuste de dinero en ventas en cada género con las combinaciones: - EU vs NA - EU vs JP - JP vs NA
Agrupamos desde 2008 que es el último cambio de la serie y hacemos contrastes:
EU_gen <- video_games[video_games$Year>=2008,] %>% group_by(Genre) %>%
summarize(Revenue = sum(EU_Sales))
NA_gen <- video_games[video_games$Year>=2008,] %>% group_by(Genre) %>%
summarize(Revenue = sum(NA_Sales))
JP_gen <- video_games[video_games$Year>=2008,] %>% group_by(Genre) %>%
summarize(Revenue = sum(JP_Sales))
Global_gen <- video_games[video_games$Year>=2008,] %>% group_by(Genre) %>%
summarize(Revenue = sum(Global_Sales))
Other_gen <- video_games[video_games$Year>=2008,] %>% group_by(Genre) %>%
summarize(Revenue = sum(Other_Sales))
NA_gen
ggplot(EU_gen,aes(x=Genre,y=Revenue))+
geom_bar(stat='identity')+
ggtitle("Genre of Games Purchased in EU")+
ylab("In Millions")+
theme(axis.text.x = element_text(angle = 90, size = 10, vjust = 0.4))

ggplot(JP_gen,aes(x=Genre,y=Revenue))+
geom_bar(stat='identity')+
ggtitle("Genre of Games Purchased in JP")+
ylab("In Millions")+
theme(axis.text.x = element_text(angle = 90, size = 10, vjust = 0.4))

ggplot(NA_gen,aes(x=Genre,y=Revenue))+
geom_bar(stat='identity')+
ggtitle("Genre of Games Purchased in NA")+
ylab("In Millions")+
theme(axis.text.x = element_text(angle = 90, size = 10, vjust = 0.4))

ggplot(NA_gen,aes(x=Genre,y=Revenue))+
geom_bar(stat='identity')+
ggtitle("Genre of Games Purchased in Other")+
ylab("In Millions")+
theme(axis.text.x = element_text(angle = 90, size = 10, vjust = 0.4))

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKRWwgcHJpbWVybyBlc3TDoSBiYXNhZG8gZW4gdW4gaGlzdMOzcmljbyBkZSB2ZW50YXMgZGUgdmlkZW9qdWVnb3MgZGUgdmFyaWFzIGNvbXBhw7HDrWFzIGVuIGRpc3RpbnRhcyBwbGF0YWZvcm1hcyBkZXNkZSBlbCBpbmljaW8gZGVsIG1lcmNhZG8gZGUgZXN0ZSBwcm9kdWN0by4gU2UgcHJldGVuZGUgb2J0ZW5lciB0ZW5kZW5jaWFzLCBkZWR1Y2lyIHF1acOpbiBjb250cm9sYSBlbCBtZXJjYWRvLCBwdW50b3MgZGUgY3Jpc2lzIG8gY2FtYmlvIGRlIGNvbnN1bW8sIHkgY3XDoWxlcyBzb24gbGFzIHBsYXRhZm9ybWFzIHF1ZSBkb21pbmFuIGVsIG1lcmNhZG8gYWN0dWFsLgoKCklkZWFzIGEgZXN0dWRpYXIgZW4gZWwgZGF0YXNldAotQ29tcGFyYXIgbGFzIHZlbnRhcyBlbnRyZSByZWdpb25lcy4gT2JzZXJ2YXIgcmVsYWNpb25lcyB5IG1vZGVsb3MgZGUgaW5mbHVlbmNpYSBlbnRyZSBsYXMgbWlzbWFzLgotVmVyIHF1w6kgZ8OpbmVyb3Mgc29uIG3DoXMgcG9wdWxhcmVzIGVuIHJlZ2lvbmVzIHkgaGFuIGNhbWJpYWRvIGEgbG8gbGFyZ28gZGVsIHRpZW1wbyBzaWduaWZpY2F0aXZhbWVudGUuCi1FbCBhbHphbWllbnRvIHkgY2HDrWRhIGRlIGRpZmVyZW50ZXMgcGxhdGFmb3JtYXMgYSBsbyBsYXJnbyBkZSBsb3MgYcOxb3MuCgpgYGB7cn0KbGlicmFyeShyZXNoYXBlMikgI2ZhY2lsaXRhIGxhIHRyYXNuZm9ybWFjacOzbiBlbnRyZSBkaWZlcmVudGVzIGZvcm1hdG9zIGRlIGRhdG9zLgpsaWJyYXJ5KHBsb3RseSkgI2h0dHBzOi8vcGxvdC5seS9yLwpgYGAKCgoKYGBge3J9CnZpZGVvX2dhbWVzPC1yZWFkLmNzdigicmVjdXJzb3MvdmdzYWxlcy5jc3YiKQp0eXBlb2YodmlkZW9fZ2FtZXMpCmhlYWQodmlkZW9fZ2FtZXMpCgp2aWRlb19nYW1lcyRZZWFyIDwtIG9yZGVyZWQodmlkZW9fZ2FtZXMkWWVhcikKdmlkZW9fZ2FtZXMgPC0gdmlkZW9fZ2FtZXNbdmlkZW9fZ2FtZXMkWWVhcjwyMDE3LF0KdmlkZW9fZ2FtZXMKCmBgYAoKClZhbW9zIGEgdmVyIGxhIHByb3BvcmNpw7NuIGRlIHZlbnRhcyBlbiByZWxhY2nDs24gYWwgdG90YWwKYGBge3J9Cm51bV9TYWxlcyA8LSB2aWRlb19nYW1lc1ssYygiTkFfU2FsZXMiLCJFVV9TYWxlcyIsIkpQX1NhbGVzIiwiT3RoZXJfU2FsZXMiLCJHbG9iYWxfU2FsZXMiKV0KYXBwbHkobnVtX1NhbGVzLDIsc3VtKS9hcHBseShudW1fU2FsZXNbJ0dsb2JhbF9TYWxlcyddLDIsc3VtKSoxMDAKCmBgYAoKRGUgZm9ybWEgZ2VuZXJhbCBwdWVkZSBhcHJlY2lhcnNlIHF1ZSBoYXkgdW5hIHN1YmlkYSBwcm9ncmFzaXZhIGRlc2RlIDE5OTYgaGFzdGEgMjAwOC4gQSBwYXJ0aXIgZGUgZXN0ZSBtb21lbnRvIGNvbWllbnphIGxhIGNhaWRhaGFzdGEgMjAxNi4gCgpgYGB7cn0KZ2dwbG90KGRhdGE9dmlkZW9fZ2FtZXMsIGFlcyh4PVllYXIsIHk9R2xvYmFsX1NhbGVzLCBmaWxsPUdlbnJlKSkgKwogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKQoKZ2dwbG90bHkoKQpgYGAKCi1Db21wYXJhciBsYXMgdmVudGFzIGVudHJlIHJlZ2lvbmVzLiBPYnNlcnZhciByZWxhY2lvbmVzIHkgbW9kZWxvcyBkZSBpbmZsdWVuY2lhIGVudHJlIGxhcyBtaXNtYXMuCgpgYGB7cn0KaGVhZCh2aWRlb19nYW1lcykKCiN2aWRlb19nYW1lc19OQT12aWRlb19nYW1lc1tjKCJZZWFyIiwiTkFfU2FsZXMiKV0KI3ZpZGVvX2dhbWVzX0VVPXZpZGVvX2dhbWVzW2MoIlllYXIiLCJFVV9TYWxlcyIpXQojdmlkZW9fZ2FtZXNfSlA9dmlkZW9fZ2FtZXNbYygiWWVhciIsIkpQX1NhbGVzIildCgpnZ3Bsb3QoZGF0YT12aWRlb19nYW1lcywgYWVzKHg9WWVhciwgeT1OQV9TYWxlcywgZmlsbD1HZW5yZSkpICsKICAgIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikKCmdncGxvdChkYXRhPXZpZGVvX2dhbWVzLCBhZXMoeD1ZZWFyLCB5PUVVX1NhbGVzLCBmaWxsPUdlbnJlKSkgKwogICAgZ2VvbV9iYXIoc3RhdD0iaWRlbnRpdHkiKQoKZ2dwbG90KGRhdGE9dmlkZW9fZ2FtZXMsIGFlcyh4PVllYXIsIHk9SlBfU2FsZXMsIGZpbGw9R2VucmUpKSArCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpCgpnZ3Bsb3QoZGF0YT12aWRlb19nYW1lcywgYWVzKHg9WWVhciwgeT1PdGhlcl9TYWxlcywgZmlsbD1HZW5yZSkpICsKICAgIGdlb21fYmFyKHN0YXQ9ImlkZW50aXR5IikKYGBgClNlIGFwcmVjaWEgcXVlIGhheSB1bmEgaW5mbHVlbmNpYSBjbGFyYSBlbnRyZSBFdXJvcGEgeSBFRVVVLiBKYXDDs24gdmEgdW4gcG9jbyBtYXMgcG9yIGxpYnJlLCBhdW5xdWUgc2UgcHVlZGUgb2JzZXJ2YXIgcXVlIGxvcyBncmFuZGVzIGNhbWJpb3MgZGUgdGVuZGVuY2lhIHRhbWJpw6luIGxlIGFmZWN0YW4uIFNlIHBvZHLDrWEgZGVjaXIgdGFtYmnDqW4gcXVlIEphcMOzbiBlcyBxdWllbiBpbmljaWEgZXNhcyB0ZW5kZW5jaWFzLiBDdWFuZG8gZW1waWV6YW4gYSBzdWJpciBsYXMgdmVudGFzLCBhIGxvcyBwb2NvcyBhw7FvcyBzdWJlbiB0YW1iacOpbiBlbiBFRVVVIHkgRXVyb3BhLiBMbyBtaXNtbyBjdWFuZG8gY29taWVuemFuIGEgY2FlciBsYXMgdmVudGFzLiBFbCByZXN0byBkZWwgbXVuZG8gc2lndWUgdGFtYmnDqW4gbGEgdGVuZGVuY2lhIGRlIEV1cm9wYSB5IEVFVVUuCgpgYGB7cn0KI1ByZXBhcm8gbG9zIGRhdG9zIHBhcmEgcG9kZXIgbW9zdHJhciB1bmEgdGVuZGVuY2lhIGRlIHZlbnRhcyBwb3IgcmVnacOzbgoKbGlicmFyeShkcGx5cikgICNmdW5jaW9uZXMgcGFyYSBtYW5pcHVsYXIgZGF0YSBmcmFtZXMuCgpuYSA8LSB2aWRlb19nYW1lcyAlPiUgc2VsZWN0KFllYXIsTkFfU2FsZXMpICU+JSBncm91cF9ieShZZWFyKSAlPiUgc3VtbWFyaXNlKHM9c3VtKE5BX1NhbGVzKSkKCmV1IDwtIHZpZGVvX2dhbWVzICU+JSBzZWxlY3QoWWVhcixFVV9TYWxlcykgJT4lIGdyb3VwX2J5KFllYXIpICU+JSBzdW1tYXJpc2Uocz1zdW0oRVVfU2FsZXMpKQoKanAgPC0gdmlkZW9fZ2FtZXMgJT4lIHNlbGVjdChZZWFyLEpQX1NhbGVzKSAlPiVncm91cF9ieShZZWFyKSAlPiUgc3VtbWFyaXNlKHM9c3VtKEpQX1NhbGVzKSkKCm90aCA8LSB2aWRlb19nYW1lcyAlPiUgc2VsZWN0KFllYXIsT3RoZXJfU2FsZXMpICU+JSBncm91cF9ieShZZWFyKSAlPiUgc3VtbWFyaXNlKHM9c3VtKE90aGVyX1NhbGVzKSkKCmRhdGFfc2FsZXMgPC0gZGF0YS5mcmFtZSh5ZWFyID0gYygxOTgwOjIwMTYpLG90aCRzLGpwJHMsZXUkcyxuYSRzKQpkYXRhX3NhbGVzCgpnZ3Bsb3QoZGF0YV9zYWxlcywgYWVzKCh5ZWFyKSkpICsgCiAgZ2VvbV9saW5lKGFlcyh5ID0gbmEkcyAsIGNvbG91ciA9ICJOQV9TYWxlcyIpLHNpemU9MSkgKyAKICBnZW9tX2xpbmUoYWVzKHkgPSBldSRzLCBjb2xvdXIgPSAiRVVfU2FsZXMiKSxzaXplPTEpKwogIGdlb21fbGluZShhZXMoeT0ganAkcyAsY29sb3VyPSdKUF9TYWxlcycpLHNpemU9MSkrCiAgZ2VvbV9saW5lKGFlcyh5PW90aCRzLGNvbG91cj0nT3RoZXJfU2FsZXMnKSxzaXplPTEpICsgeWxhYignVmVudGFzIGVuIE1pbGxvbmVzJykgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzY2FsZXM6OnByZXR0eV9icmVha3MobiA9IDkpKSArICAjTnVtZXJvIGRlIGRpdmlzaW9uZXMgZW4gWC4KICBnZ3RpdGxlKCJFdm9sdWNpw7NuIGRlIHZlbnRhcyBhIGxvIGxhcmdvIGRlbCB0aWVtcG8iKSArCiAgI3RoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHNpemUgPSAxMCwgdmp1c3QgPSAwLjQpLGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQogIHRoZW1lKHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChmaWxsID0gImdyZXkiKSxsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCwgY29sb3VyID0gImJsdWUiKSxsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoZmFjZT0iYm9sZCIpLGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQoKI2hheSBkaWZlcmVudGVzIHRpcG9zIGRlIHRoZW1lcyBwcmVkZWZpbmlkb3M6IHRoZW1lX2JmLi4uIHRoZW1lX2dyYXkuLi4gIFZlciBodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy9yZWZlcmVuY2UvdGhlbWUuaHRtbAoKYGBgClNlIG9ic2VydmEgdW5hIGRvbWluYWNpw7NuIGVuIGxhcyB2ZW50YXMgcG9yIHBhcnRlIGRlIE5BIGVudHJlIDIwMDAgeSAyMDEwLCBBIHBhcnRpciBkZSAyMDA4IHkgY29pbmNpZGllbmRvIGNvbiBsYSBjcmlzaXMgZ2xvYmFsIGVjb27Ds21pY2EsIGhheSB1bmEgY2HDrWRhIGZ1ZXJ0ZSBlbiB0b2RhcyBsYXMgcmVnaW9uZXMgeSBsYSBkb21pbmFjacOzbiBjZXNhLgoKSGF5IHBvciBsbyB0YW50byBwdW50b3MgY3LDrXRpY29zIGVuIGxhIGV2b2x1Y2nDs24gZGUgbGFzIHZlbnRhcyBlbiAxOTk1LCAyMDAwIHkgMjAwOCAoc2UgcG9kcsOtYSBpbmRhZ2FyIHF1w6kgbW90aXZvcyBmb3J6YXJvbiBsb3MgY2FtYmlvcyBlbiBsYXMgZmVjaGFzIHByZXZpYXMgbm8gY29tZW50YWRhcykuCgpBIHN1IHZleiBzZSBvYnNlcnZhIHF1ZSBsYSBzZXJpZSBOQSB5IEVVIGVzdMOhbiBmdWVydGVtZW50ZSBsaWdhZGFzLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCi1FbCBhbHphbWllbnRvIHkgY2HDrWRhIGRlIGRpZmVyZW50ZXMgcGxhdGFmb3JtYXMgYSBsbyBsYXJnbyBkZSBsb3MgYcOxb3MuCgpgYGB7cn0KcGxhdGZvcm1zIDwtIHZpZGVvX2dhbWVzWyxjKCJQbGF0Zm9ybSIsIlllYXIiLCJHbG9iYWxfU2FsZXMiKV0KcGxhdGZvcm1zIDwtIHBsYXRmb3JtcyAlPiUgZ3JvdXBfYnkoUGxhdGZvcm0sWWVhcikgJT4lIHN1bW1hcmlzZV9hbGwoZnVucyhzdW0pKQoKcGxhdGZvcm1zXzE5ODA8LXN1YnNldChwbGF0Zm9ybXMsWWVhcjwxOTkwLHNlbGVjdCA9IFBsYXRmb3JtOkdsb2JhbF9TYWxlcykKcGxhdGZvcm1zXzE5OTA8LXN1YnNldChwbGF0Zm9ybXMsWWVhcj49MTk5MCAmIFllYXI8MjAwMCxzZWxlY3QgPSBQbGF0Zm9ybTpHbG9iYWxfU2FsZXMpCnBsYXRmb3Jtc18yMDAwPC1zdWJzZXQocGxhdGZvcm1zLFllYXI+PTIwMDAgJiBZZWFyPDIwMTAsc2VsZWN0ID0gUGxhdGZvcm06R2xvYmFsX1NhbGVzKQpwbGF0Zm9ybXNfMjAxMDwtc3Vic2V0KHBsYXRmb3JtcyxZZWFyPj0yMDEwLHNlbGVjdCA9IFBsYXRmb3JtOkdsb2JhbF9TYWxlcykKCgpzcCA8LSBnZ3Bsb3QocGxhdGZvcm1zXzE5ODAsIGFlcyh4PVllYXIsIHk9R2xvYmFsX1NhbGVzKSkgKwogIGdlb21fcG9pbnQoc2hhcGU9MSkgKwogIGdlb21fbGluZShncm91cCA9IDEpCnNwICsgZmFjZXRfZ3JpZChQbGF0Zm9ybSB+IC4pCgpzcCA8LSBnZ3Bsb3QocGxhdGZvcm1zXzE5OTAsIGFlcyh4PVllYXIsIHk9R2xvYmFsX1NhbGVzKSkgKwogIGdlb21fcG9pbnQoc2hhcGU9MSkgKwogIGdlb21fbGluZShncm91cCA9IDEpCnNwICsgZmFjZXRfd3JhcChQbGF0Zm9ybSB+IC4sIG5jb2w9MykgCgpzcCA8LSBnZ3Bsb3QocGxhdGZvcm1zXzIwMDAsIGFlcyh4PVllYXIsIHk9R2xvYmFsX1NhbGVzKSkgKwogIGdlb21fcG9pbnQoc2hhcGU9MSkgKwogIGdlb21fbGluZShncm91cCA9IDEpCnNwICsgZmFjZXRfd3JhcChQbGF0Zm9ybSB+IC4sIG5jb2w9MykgIAoKc3AgPC0gZ2dwbG90KHBsYXRmb3Jtc18yMDEwLCBhZXMoeD1ZZWFyLCB5PUdsb2JhbF9TYWxlcykpICsKICBnZW9tX3BvaW50KHNoYXBlPTEpICsKICBnZW9tX2xpbmUoZ3JvdXAgPSAxKQpzcCArIGZhY2V0X3dyYXAoUGxhdGZvcm0gfiAuLCBuY29sPTMpICAKCiNQYXJhIGxvcyBncsOhZmljb3MgZGUgbMOtbmVhcywgbG9zIHB1bnRvcyBkZSBkYXRvcyBkZWJlbiBhZ3J1cGFyc2UgcGFyYSBxdWUgc2VwYSBxdcOpIHB1bnRvcyBjb25lY3Rhci4gRW4gZXN0ZSBjYXNvLCBlcyBzaW1wbGU6IHRvZG9zIGxvcyBwdW50b3MgZGViZW4gZXN0YXIgY29uZWN0YWRvcywgcG9yIGxvIHF1ZSBncm91cCA9IDEuIEN1YW5kbyBzZSB1dGlsaXphbiBtw6FzIHZhcmlhYmxlcyB5IHNlIGRpYnVqYW4gdmFyaWFzIGzDrW5lYXMsIGxhIGFncnVwYWNpw7NuIGRlIGzDrW5lYXMgc2UgcmVhbGl6YSBnZW5lcmFsbWVudGUgcG9yIHZhcmlhYmxlLgoKCgoKYGBgCgoKClZlciBxdcOpIGfDqW5lcm9zIHNvbiBtw6FzIHBvcHVsYXJlcyBlbiByZWdpb25lcyB5IGhhbiBjYW1iaWFkbyBhIGxvIGxhcmdvIGRlbCB0aWVtcG8gc2lnbmlmaWNhdGl2YW1lbnRlLgoKVmFtb3MgYSB2ZXIgZWwgVE9QIGRlIGxvcyBnw6luZXJvcyBwb3IgYcOxbwpgYGB7cn0KCiNMYSBmdW5jacOzbiB0b3BfbiB0ZSBwZXJtaXRlIHF1ZWRhcnRlIGNvbiBlbCBwcmltZXIgdmFsb3I6CnRvcF9nZW5yZV95ZWFyIDwtIHZpZGVvX2dhbWVzWyxjKCJHZW5yZSIsIlllYXIiLCJHbG9iYWxfU2FsZXMiKV0KdG9wX2dlbnJlX3llYXIgPC0gdG9wX2dlbnJlX3llYXIgJT4lIGdyb3VwX2J5KFllYXIsR2VucmUpICU+JSBzdW1tYXJpc2UodmVudGFzPXN1bShHbG9iYWxfU2FsZXMpKSAlPiUgdG9wX24oMSkKCnRvcF9nZW5yZV9qYXBhbiA8LSB2aWRlb19nYW1lc1ssYygiR2VucmUiLCJZZWFyIiwiSlBfU2FsZXMiKV0KdG9wX2dlbnJlX2phcGFuIDwtIHRvcF9nZW5yZV9qYXBhbiAlPiUgZ3JvdXBfYnkoWWVhcixHZW5yZSkgJT4lIHN1bW1hcmlzZSh2ZW50YXM9c3VtKEpQX1NhbGVzKSkgJT4lIHRvcF9uKDEpCgpnZ3Bsb3QoZGF0YT10b3BfZ2VucmVfeWVhciwgYWVzKHg9WWVhciwgeT12ZW50YXMsIGZpbGw9R2VucmUpKSArCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsKICAgIGdndGl0bGUoIlRvcCBHZW5lcm8gcG9yIGHDsW8iKSArCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBzaXplID0gMTAsIHZqdXN0ID0gMC40KSxsZWdlbmQucG9zaXRpb24gPSAidG9wIikKCmdncGxvdChkYXRhPXRvcF9nZW5yZV9qYXBhbiwgYWVzKHg9WWVhciwgeT12ZW50YXMsIGZpbGw9R2VucmUpKSArCiAgICBnZW9tX2JhcihzdGF0PSJpZGVudGl0eSIpICsKICAgIGdndGl0bGUoIlRvcCBHZW5lcm8gcG9yIGHDsW8gSmFwb24iKSArCiAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCBzaXplID0gMTAsIHZqdXN0ID0gMC40KSxsZWdlbmQucG9zaXRpb24gPSAidG9wIikKYGBgCk9ic2VydmFtb3MgcXVlIGxhIHByZWZlcmVuY2lhIGVuIGfDqW5lcm8gZGUgdmlkZW9qdWVnbyBlbiBKYXDDs24gZXMgcG9yIGxvcyBqdWVnb3MgZGUgcm9sIG1pZW50cmFzIHF1ZSBnbG9iYWxtZW50ZSBlcyBwb3IgbG9zIGRlIGFjY2nDs24uIEVzdG8gZXMgdW5hIGNhcmFjdGVyw61zdGljYSBjdWFsaXRhdGl2YSBkaWZlcmVuY2lhZG9yYSBkZSBlc3RlIG1lcmNhZG8gcmVzcGVjdG8gYWwgZ2xvYmFsLgoKLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tClJlYWxpemFtb3MgdW4gY29udHJhc3RlIENoaSBDdWFkcmFkbyBkZSBib25kYWQgZGUgYWp1c3RlIGRlIGRpbmVybyBlbiB2ZW50YXMgZW4gY2FkYSBnw6luZXJvIGNvbiBsYXMgY29tYmluYWNpb25lczogLSBFVSB2cyBOQSAtIEVVIHZzIEpQIC0gSlAgdnMgTkEKCkFncnVwYW1vcyBkZXNkZSAyMDA4IHF1ZSBlcyBlbCDDumx0aW1vIGNhbWJpbyBkZSBsYSBzZXJpZSB5IGhhY2Vtb3MgY29udHJhc3RlczoKYGBge3J9CkVVX2dlbiA8LSB2aWRlb19nYW1lc1t2aWRlb19nYW1lcyRZZWFyPj0yMDA4LF0gJT4lIGdyb3VwX2J5KEdlbnJlKSAlPiUgCiAgICAgICAgIHN1bW1hcml6ZShSZXZlbnVlID0gc3VtKEVVX1NhbGVzKSkKTkFfZ2VuIDwtIHZpZGVvX2dhbWVzW3ZpZGVvX2dhbWVzJFllYXI+PTIwMDgsXSAlPiUgZ3JvdXBfYnkoR2VucmUpICU+JSAKICAgICAgICAgc3VtbWFyaXplKFJldmVudWUgPSBzdW0oTkFfU2FsZXMpKQpKUF9nZW4gPC0gdmlkZW9fZ2FtZXNbdmlkZW9fZ2FtZXMkWWVhcj49MjAwOCxdICU+JSBncm91cF9ieShHZW5yZSkgJT4lIAogICAgICAgICBzdW1tYXJpemUoUmV2ZW51ZSA9IHN1bShKUF9TYWxlcykpCkdsb2JhbF9nZW4gPC0gdmlkZW9fZ2FtZXNbdmlkZW9fZ2FtZXMkWWVhcj49MjAwOCxdICU+JSBncm91cF9ieShHZW5yZSkgJT4lIAogICAgICAgICBzdW1tYXJpemUoUmV2ZW51ZSA9IHN1bShHbG9iYWxfU2FsZXMpKQpPdGhlcl9nZW4gPC0gdmlkZW9fZ2FtZXNbdmlkZW9fZ2FtZXMkWWVhcj49MjAwOCxdICU+JSBncm91cF9ieShHZW5yZSkgJT4lIAogICAgICAgICBzdW1tYXJpemUoUmV2ZW51ZSA9IHN1bShPdGhlcl9TYWxlcykpCgpOQV9nZW4KYGBgCmBgYHtyfQpnZ3Bsb3QoRVVfZ2VuLGFlcyh4PUdlbnJlLHk9UmV2ZW51ZSkpKwogIGdlb21fYmFyKHN0YXQ9J2lkZW50aXR5JykrIAogIGdndGl0bGUoIkdlbnJlIG9mIEdhbWVzIFB1cmNoYXNlZCBpbiBFVSIpKwogIHlsYWIoIkluIE1pbGxpb25zIikrCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgc2l6ZSA9IDEwLCB2anVzdCA9IDAuNCkpCgoKZ2dwbG90KEpQX2dlbixhZXMoeD1HZW5yZSx5PVJldmVudWUpKSsKICBnZW9tX2JhcihzdGF0PSdpZGVudGl0eScpKyAKICBnZ3RpdGxlKCJHZW5yZSBvZiBHYW1lcyBQdXJjaGFzZWQgaW4gSlAiKSsKICB5bGFiKCJJbiBNaWxsaW9ucyIpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHNpemUgPSAxMCwgdmp1c3QgPSAwLjQpKQoKZ2dwbG90KE5BX2dlbixhZXMoeD1HZW5yZSx5PVJldmVudWUpKSsKICBnZW9tX2JhcihzdGF0PSdpZGVudGl0eScpKyAKICBnZ3RpdGxlKCJHZW5yZSBvZiBHYW1lcyBQdXJjaGFzZWQgaW4gTkEiKSsKICB5bGFiKCJJbiBNaWxsaW9ucyIpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHNpemUgPSAxMCwgdmp1c3QgPSAwLjQpKQoKZ2dwbG90KE5BX2dlbixhZXMoeD1HZW5yZSx5PVJldmVudWUpKSsKICBnZW9tX2JhcihzdGF0PSdpZGVudGl0eScpKyAKICBnZ3RpdGxlKCJHZW5yZSBvZiBHYW1lcyBQdXJjaGFzZWQgaW4gT3RoZXIiKSsKICB5bGFiKCJJbiBNaWxsaW9ucyIpKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHNpemUgPSAxMCwgdmp1c3QgPSAwLjQpKQpgYGAKCgoKCgoK